﻿using System;
using System.Collections.Generic;

namespace WordsGame
{
    internal class Game
    {
        private IList<string> _words;
        private bool _isActive;
        private Dictionary<char, int> _characters;
        private Tree _validWords;
        private Random _random = new Random((int)DateTime.Now.Ticks);
        private Tree _usedWords;
        private Standings _standings;
        private IStandingsProvider _provider;

        public string CurrentWord { get; set; }

        public bool IsActive { get { return _isActive; } }

        public Game(IList<string> words, Tree validWords, IStandingsProvider provider)
        {
            _provider = provider;
            _standings = provider.Load();
            _validWords = validWords;
            _isActive = false;
            _words = words;
            CurrentWord = string.Empty;
        }

        public void Start()
        {
            if (_words.Count > 0)
            {
                CurrentWord = _words[_random.Next(_words.Count)];
                
                _characters = StringToOccurences(CurrentWord);
                _isActive = true;

                _usedWords = new Tree();
            }
        }

        public void Stop()
        {
            if (_isActive)
            {
                CurrentWord = string.Empty;
                _isActive = false;
                _provider.Save(_standings);
            }
        }

        public int MakeMove(string player, string word)
        {
            if (!_isActive || string.Compare(word, CurrentWord, StringComparison.OrdinalIgnoreCase) == 0)
            {
                return 0;
            }

            Dictionary<char, int> wordChars = StringToOccurences(word);

            foreach (var pair in wordChars)
            {
                if (!_characters.ContainsKey(pair.Key) || pair.Value > _characters[pair.Key])
                {
                    return 0;
                }
            }

            int score = 0;
            if (_validWords.Contains(word) && !_usedWords.Contains(word))
            {
                _usedWords.Add(word);
                score = word.Length;
                _standings.Change(player, score);
            }

            if (score > 0)
            {
                _provider.Save(_standings);
            }

            return score;
        }

        private static Dictionary<char, int> StringToOccurences(string word)
        {
            var characters = new Dictionary<char, int>();
            foreach (var ch in word)
            {
                if (characters.ContainsKey(ch))
                {
                    characters[ch]++;
                }
                else
                {
                    characters[ch] = 0;
                }
            }

            return characters;
        }

        public Standings GetStandings()
        {
            return _standings;
        }
    }
}
